﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Web;

namespace MvcApplication2.Models
{
    /*
     * 05/07/2012
     * Il discorso UserMessage si stà complicando oltremodo .
     * - Non mi interessano biforcazioni su commenti
     * - Le discussioni saranno tra 2 persone.
     * - Nella maniera come lo sto facendo ora (UserMessage "superclasse") devo necessariamente
     *   ripetere i permessi o tenere riferimento al messaggio iniziale. 
     * Proverei in questa maniera.
     *  Classe ThreadMessage ( inizio commento o trattativa )
     *      Child<UserMessage> ( messaggi da parte di utente)
     */

    /// <summary>
    /// Classe usata per iniziare commento o trattativa
    /// </summary>
    public class UserMessage
    {
        public UserMessage()
        {
            UserMessages = new HashSet<UserMessage>();
            UsersAllowed = new HashSet<UserProfile>();
            ReadByUser = new HashSet<UserProfile>();
        }

        public int UserMessageId { get; set; }


        public virtual ICollection<UserMessage> UserMessages { get; set; }

        /// <summary>
        /// Questa stringa mi identifica il tipo di thread
        /// </summary>
        public string Type { get; set; }

        /// <summary>
        /// Owner è chi crea il messaggio.
        /// </summary>
        public int OwnerId { get; set; }
        public UserProfile Owner { get; set; }

        /// <summary>
        /// False per commenti.
        /// </summary>
        public bool PrivateThread { get; set; }

        /// <summary>
        /// Lista di utente che possono partecipare alla discussione
        /// </summary>
        public ICollection<UserProfile> UsersAllowed { get; set; }

        /// <summary>
        /// Lista di utenti che hanno letto il messaggio.
        /// Si utilizza solamente nei messaggi personali.
        /// Non nei commenti.
        /// Viene resettato quando viene effettuato una modifica.
        /// </summary>
        public ICollection<UserProfile> ReadByUser { get; set; }

        /// <summary>
        /// todo : forse è meglio usare id del ultimo che ha mandato messaggio
        /// </summary>
        public string LastMessageFrom { get; set; }

        public int? ExerciseId { get; set; }
        public Exercise Exercise { get; set; }

        public int? TesterId { get; set; }
        public UserProfile Tester { get; set; }

        public string Currency { get; set; }
        public string ExerciseStatus { get; set; }

        public DateTime? CreationDate { get; set; }
        public DateTime? LastMessageDate { get; set; }
        /*
         * Impostazione sistema messaggi.
         * All'interno del sito utenti si possono scambiare messaggi ( non mail ).
         * Sono arrivato alla conclusione che questi messaggi li devo gestire come thread.
         * Un thread ( messaggio ) può esserre :
         *      - Generico ( richiesta informale di informazione )
         *      - Generico con riferimento a esercizio  
         *      - Strutturato ( richiesta specifica )
         *          - Proposta di lavoro ( dev <-> tester )
         *          - Controproposte
         *      - ? Sistema di commenti relativo a qualcosa ( utente , esercizio , valutazione )
         *          
         * Ogni messaggio può avere più destinatari.
         * 
         * Più che un sistema di messaggi , fare tipo un thread , in modo da avere sempre il filo della discussione.
         *  Deve ricordare più una chat che un sistema di mail.
         *  
         * I messaggi sono salvati dentro database.
         * 
         * - - Considerazioni - -
         * 
         * Quando mando messaggio , lo devo duplicare in modo che destinatario ne abbia una propria copia. NO
         * 
         * Oppure metto un flag tipo delected ? NO
         * 
         * - - OK - Thread con solo destinatari capaci di leggere il messaggio.
         * 
         * Oppure al posto di messaggio creo un thread e do la possibilita al destinatario di partecipare ( leggere i messaggi )
         * 
         * - - OK - che con più destinatari si aprano più thread. ( evito errori )
     
         */

        /// <summary>
        /// Generic message - comment -
        /// 
        /// TESTER EXERCISE ESERCIZIO TEST (LAVORO)
        /// Lo stato di un esercizio di test , o iter.
        /// - proposta ( dev o tester propongono esercizio )
        ///  ( - tempo di consegna ? )
        /// - si può ribattere su prezzo fino a che tutte e 2 le parti sono daccordo
        /// - in attesa di testing
        /// - in attesa di pagamento
        /// - completato. ( invito a dare valutazioni )
        /// Per salvare stato uso stringa o byte ? faccio byte , dovro comunque cambiare in stringa magari usando automapper.
        /// o aggiungo proprietà da escludere con ef?
        /// Un esercizio (lavoro ) ( trova altro nome).
        /// Il rapporto tra dev e tester riguardo un esercizio da svolgere è gestito dalla classe 
        /// thredmessage.
        /// In caso di invi multipli, penso che creerò tanti UserMessage principali.
        /// Magari poi li raggruppo in base a esercizio.
        /// 
        /// Qui dev o tester creano il messaggio, con riferimento a esercizio, 
        /// l'ultimo che propone il prezzo. l'altro può fare nuova offerta o accettare.
        /// quando si trova un'accordo. esercizio va in coda da tester e da dev.
        /// 
        /// 
        /// REPUTAZIONE
        /// La reputazione è formata da insieme di commenti con giudizio.
        /// 
        ///  - fare promemoria sui giudizi da dare.
        ///  - il voto si può modificare ( solo da chi la dato ).
        ///  - solo chi ha lavorato insieme può dare un commento riguardante un certo lavoro.
        ///  - si può lasciare un voto all'esericizio svolto e al developer.
        ///  - chiunque può lasciare commenti su giudizio ad altri .
        /// ---
        /// Penso di usare anche qui UserMessage.
        /// Thread Principale
        /// -> figli voti assegnati
        ///     -> ogni voto può aprire thread.
        /// 
        /// -- Non creo altra struttura perchè grossomodo mi servono le stesse proprietà
        ///   di accesso e di gerarchia.
        /// 
        /// -- inserire anche date ti aggiornamento e creazione esercizi e proposte di lavoro.
        /// 
        /// </summary>


        public string Subject { get; set; }

        #region RatingSytem

        public byte Rating { get; set; }

        public UserProfile RatedUser { get; set; }
        public UserMessage RatingExerciseRef { get; set; }
        /// <summary>
        /// Coulde be a rating note.
        /// or comment
        /// </summary>
        public string Message { get; set; }

        #endregion

        #region Tester Exercise

        /*
         * Questa classe la uso anche per gestire le trattative di lavoro.
         * 
         */

        // indica se l'ultima offerta è stata data da dev oppure da tester.
        // A seconda di chi dà l'ultima offerta , l'altro può accettare immediatamente oppure rilanciare

        /// <summary>
        /// Nel sistema di rating, l'exercise 
        /// </summary>


        /*
         * voglio capacità di lasciare messaggi con proposta?
         * 
         * in modo che assomigli tipo a chat.
         * 
         * [Tester] Username : messgaatioi     4.5 € 
         * [dev]    Username : messgaatioi     4 € 
         * 
         * e in maniera simile voglio aprire dialoghi generici e cancellazioni lavori in corso.
         * 
         * messaggio azione.
         * 
         * indi il modo che cambio il prezzo come faccio ora non è ok.
         * ma devo creare un 'message' per ogni scambio di inf.
         * 
         * quindi quando faccio send. creo ma non aggiiungo al database,
         * prendo ultimo prezzo della gerarchia.
         * 
         * message ini. 
         * child.0 < parente del successivo.
         * child.0 
         * 
         * quando message non ha più figli chiudo 
         */

        // uso solo dollari. 


        public double Reward { get; set; }

        #endregion

        public int LastMessageUserId { get; set; }

        public string LastMessageTo { get; set; }

        public string LastBidFrom { get; set; }
    }

    /// <summary>
    /// Fondere type con status ??
    /// Ricorda che il confronta lo fa lettera per lettera,
    /// Quindi magari fai stringhe brevi e con differenza nella parte iniziale
    /// </summary>
    public class UserMessageType
    {
        /**
         * I messaggi di tipo system-info sono messaggi di notifica che manda il sistema quando succedde particolare evento.
         * Votazione- cancellazione-ecc-
         */
        public const string SystemInfo = "sys-info";
        public const string TesterExercise = "test-ex";
        public const string RatingDev = "dev-rat";
        public const string RatingTester = "test-rat";

        //  public const string GenericMessageChild = "c-gen-mes";
        public const string GenericMessage = "gen-mes";

        public const string MessageChild = "c-mes";

        public const string TesterExerciseMessage = "c-test-ex";

    }

    /// <summary>
    /// Quasi quasi riuso string al posto di byte.
    /// Usando enum è importante ordine.
    /// Con string inoltre è più versatile.
    /// </summary>
    public class ExerciseStatusType
    {
        // Utente propone ad altro lavoro dev <> tester, durante la trattativa rimane in questo stato
        public const string ProposalActive = "proposal-active";
      //  public const string ProposalInactive = "proposal-inactive";
        // ? 
        // TestStarted ?? - encoding- uploading ?
        // In attesa del testing
        public const string WaitingTest = "waiting-test";

        // In attesa del pagamento
        public const string WaitingPayment = "waiting-payment";

        // Esercizio completato , il video è disponibile e tester è stato pagato
        // Quando si arriva qui è possibile dare i rating
        public const string Completed = "completed";

        // Utente destinatario declina proposta.
        public const string Rejected = "rejected";

        // l'esercizio è cancellato dopo che avvenuto accordo.
        // meglio non poterlo eliminare dopo che è avvenuta proposta.
        // Si può avere la possibilità di eliminarlo in ogni stato dopo l'accordo.
        // Avvisando che si riceverà giudizio negativo da parte utente.
        public const string Eliminated = "eliminated";
    }

    /*
     * cosa capita quando utente non vuole pagare una volta effettuato il test 
     */

}